import NavigatedViewer from 'bpmn-js/lib/NavigatedViewer'

// import ModelingModule from 'bpmn-js/lib/features/modeling';
// import AutoPlaceModule from 'bpmn-js/lib/features/auto-place';
// import MoveCanvasModule from 'diagram-js/lib/navigation/movecanvas'
// import ZoomScrollModule from 'diagram-js/lib/navigation/zoomscroll'
// import KeyboardMoveModule from 'diagram-js/lib/navigation/keyboard-move'

const classNames = {
  currentActivity: 'current-activity'
}

export class UBpmnViewer extends NavigatedViewer {
  /** @type {import('../types').Canvas} */
  canvas
  /**
   * @type {HTMLElement}
   */
  get container() {
    return this._container
  }
  /**
   * 用于生成、管理bpmn专用xml文件
   * @type {import('../types').Modeling}
   */
  modeling
  /**
   * 元素注册表
   * @type {import('../types').ElementRegistry}
   */
  elementRegistry
  /**
   * 事件总线
   * @type {import('../types').EventBus}
   */
  eventBus
  _enables = {
    zoomable: false,
    moveable: false
  }
  _resetLastCurrent
  /**
   * @param {Object} [options] 传递给viewer的配置选项
   * @param {HTMLElement|string} [options.container] 容器，默认为body
   * @param {string|number} [options.width] 视图宽度
   * @param {string|number} [options.height] 视图高度
   * @param {Object} [options.moddleExtensions] 扩展包
   * @param {Array} [options.modules] 覆盖默认模块的模块列表
   * @param {Array} [options.additionalModules] 与默认模块一起使用的模块列表
   * @param {boolean} [options.moveable] 是否可通过鼠标移动
   * @param {boolean} [options.zoomable] 是否可通过鼠标滚轮缩放
   */
  constructor(options) {
    // options.additionalModules = options.additionalModules ?? []
    // options.additionalModules.push(MoveCanvasModule, KeyboardMoveModule, ZoomScrollModule)

    super(options)

    this._enables.moveable = options.moveable ?? false
    this._enables.zoomable = options.moveable ?? false
    this.on('import.done', () => {
      // 调整画布位置，适应当前可视区域
      this.canvas.zoom('fit-viewport')
    })
    this.init()
  }
  init() {
    try {
      this.canvas = this.get('canvas')
      this.eventBus = this.get('eventBus')
      this.elementRegistry = this.get('elementRegistry')
      this.modeling = this.get('modeling')

      this.eventBus.on('element.mousedown', (ev) => {
        if (!this._enables.moveable) {
          ev.preventDefault()
          ev.stopPropagation()
          // event.stopImmediatePropagation()
        }
      })

      this.canvas._svg.addEventListener('wheel', (ev) => {
        if (!this._enables.zoomable) {
          // ev.preventDefault()
          ev.stopPropagation()
          // ev.stopImmediatePropagation()
        }
      })
    } catch (error) {
      console.error('UBpmnModeler init error: ', error)
    }

    // 删除右下角qx声明  (禁止这么做！)
    // 参考许可证: https://bpmn.io/license/
    const bpmnPowerBy = this.container.querySelector('a.bjs-powered-by')
    if (bpmnPowerBy) {
      bpmnPowerBy.remove()
    }
  }
  zoomable(enable = true) {
    this._enables.zoomable = enable
  }
  moveable(enable = true) {
    this._enables.moveable = enable
  }
  /**
   *
   * @param {string} xml bpmn文件内容
   * @param {(result:import('../types').ImportXMLResult)=>void} [callback] 加载完成的回调(会出现警告)
   * @returns {Promise<ImportXMLResult>}
   */
  importXML(xml, callback) {
    return super.importXML(xml, callback)
  }
  fitViewport() {
    this.canvas.zoom('fit-viewport')
  }
  /**
   *
   */
  setCurrentNode(id) {
    // 先取消已有的当前节点
    this.container.querySelector(`g.${classNames.currentActivity}`)?.classList.remove(classNames.currentActivity)

    console.log(this.elementRegistry)

    let targetNode, keys
    if (id === 'Start') {
      keys = this.elementRegistry._elements
      for (const key of keys) {
        if (this.elementRegistry._elements[key].element.type === 'bpmn:StartEvent') {
          targetNode = this.elementRegistry._elements[key].gfx
          break
        }
      }
    } else if (id === 'End') {
      for (const key of keys) {
        if (this.elementRegistry._elements[key].element.type === 'bpmn:EndEvent') {
          targetNode = this.elementRegistry._elements[key].gfx
          break
        }
      }
    } else {
      targetNode = this.elementRegistry.getGraphics(id)
    }

    targetNode?.classList.add(classNames.currentActivity)

    console.log('setCurrent', id, targetNode)
  }
  /**
   * 根据名称获取bpmn指定供应商
   * @template {keyof import('../types/provider').BPMNProviderMap} T
   * @param {T} name 名称
   * @param {boolean} [strict] 严格模式，如果为false，则将缺失的服务解析为空
   * @returns {import('../types/provider').BPMNProviderMap[T]}
   */
  get(name, strict) {
    return super.get(name, strict)
  }
  /**
   * @param {import('../types').EventName|Array<import('../types').EventName>} events
   * @param {number|import('../types').EventCallBack} [priority=1000] 调用该侦听器的优先级越大越高,如果为函数则作为回调
   * @param {import('../types').EventCallBack} callback
   * @param {Object} [that] 回调函数的上下文this参数
   */
  on(events, priority, callback, that) {
    return super.on(events, priority, callback, that)
  }
  /**
   * @param {import('../types').EventName|Array<import('../types').EventName>} events
   * @param {number|import('../types').EventCallBack} [priority=1000] 调用该侦听器的优先级越大越高,如果为函数则作为回调
   * @param {import('../types').EventCallBack} callback
   * @param {Object} [that] 回调函数的上下文this参数
   */
  once(events, priority, callback, that) {
    return this.eventBus.once(events, priority, callback, that)
  }
  /**
   * 如果没有给出回调，则将删除给定事件名称的所有侦听器。
   * @param {import('../types').EventName|Array<import('../types').EventName>} events
   * @param {import('../types').EventCallBack} callback
   */
  off(events, callback) {
    return super.off(events, callback)
  }
}
